import java.time.DayOfWeek;
import java.util.LinkedList;
import java.util.List;

public class ChargeStandard {

    private List<WeekdayRangeChargeInfo> weekdayRangeChargeInfos;

    public ChargeStandard() {
        this.weekdayRangeChargeInfos = new LinkedList<>();
    }

    public void addWeekdayRangeChargeInfo(WeekdayRangeChargeInfo wrci) {
        this.weekdayRangeChargeInfos.add(wrci);
    }

    public int calculateChargeMoney(DayOfWeek targetDay, int beginTime, int endTime) {
        int chargeMoney = 0;
        for (WeekdayRangeChargeInfo info : this.weekdayRangeChargeInfos) {
            if (info.checkInRange(targetDay)) {
                chargeMoney = info.computeChargeMoney(beginTime, endTime);
                break;
            }
        }

        return chargeMoney;
    }

    public int calculatePenaltyMoney(DayOfWeek targetDay, int money) {
        int penaltyMoney = 0;
        for (WeekdayRangeChargeInfo info : this.weekdayRangeChargeInfos) {
            if (info.checkInRange(targetDay)) {
                penaltyMoney = info.computePenaltyMoney(money);
                break;
            }
        }

        return penaltyMoney;
    }

    /**
     * 按照星期几划分的收费标准
     */
    public static class WeekdayRangeChargeInfo {
        private DayOfWeek startDay;
        private DayOfWeek stopDay;
        private int penalty;

        List<TimeRangeChargeInfo> timeRangeChargeInfos;

        WeekdayRangeChargeInfo(DayOfWeek start, DayOfWeek stop, int penalty) {
            this.startDay = start;
            this.stopDay = stop;
            this.penalty = penalty;
            this.timeRangeChargeInfos = new LinkedList<>();
        }

        public void addTimeRangeChargeInfo(int starth, int stoph, int unit) {
            TimeRangeChargeInfo trci = new TimeRangeChargeInfo(starth, stoph, unit);
            this.timeRangeChargeInfos.add(trci);
        }

        public int computePenaltyMoney(int money) {
            return money * this.penalty / 100;
        }

        public int computeChargeMoney(int beginTime, int endTime) {
            int charge = 0;
            for (TimeRangeChargeInfo info : this.timeRangeChargeInfos) {
                charge += info.chargeInRange(beginTime, endTime);
            }

            return charge;
        }

        public boolean checkInRange(DayOfWeek target) {
            int st = this.startDay.getValue();
            int sp = this.stopDay.getValue();
            int t = target.getValue();

            if (((st > sp) && (t > sp || t < st)) || ((st < sp) && (t < st || t > sp)) || ((st == sp) && t != st))
                return false;

            return true;
        }
    }

    /**
     * 按照时间段划分的收费标准
     */
    public static class TimeRangeChargeInfo {
        private int startHour;
        private int stopHour;
        private int unitPrice;

        TimeRangeChargeInfo(int start, int stop, int price) {
            this.startHour = start;
            this.stopHour = stop;
            this.unitPrice = price;
        }

        public int chargeInRange(int begin, int end) {
            int bg = this.startHour;
            int ed = this.stopHour;
            if (this.startHour < begin)
                bg = begin;

            if (this.stopHour > end)
                ed = end;

            if (ed > bg)
                return (ed - bg) * this.unitPrice;

            return 0;
        }
    }
}